﻿package org.dm.math 
{
	/**
	 * ...
	 * @author Scott
	 */
	public class Num3
	{
		public var x:Number;
		public var y:Number;
		public var z:Number;

		static private var temp:Num3 = Num3.ZERO;
		
		static public var toDEGREES :Number = 180/Math.PI;
		static public var toRADIANS :Number = Math.PI/180;
		
		public function Num3( x:Number = 0, y:Number = 0, z: Number=0 )
		{
			this.x = x;
			this.y = y;
			this.z = z;
		}

		public function clone():Num3
		{
			return new Num3( this.x, this.y, this.z );
		}
		
		public function copyTo(n:Num3):void
		{
			n.x = x;
			n.y = y;
			n.z = z;
		}	
		
		public function copyFrom(n:Num3):void
		{
			x = n.x; 
			y = n.y; 
			z = n.z; 
		}
		
		public function reset(newx:Number = 0, newy:Number = 0, newz:Number = 0):void
		{
			x = newx; 
			y = newy; 
			z = newz; 
		}

		public function get modulo():Number
		{
			return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z );
		}
		
		public static function add( v:Num3, w:Num3 ):Num3
		{
			return new Num3
			(
				v.x + w.x,
				v.y + w.y,
				v.z + w.z
			);
		}
		
		public static function sub( v:Num3, w:Num3 ):Num3
		{
			return new Num3
			(
				v.x - w.x,
				v.y - w.y,
				v.z - w.z
			);
		}
		
		public static function dot( v:Num3, w:Num3 ):Number
		{
			return ( v.x * w.x + v.y * w.y + w.z * v.z );
		}
		
		public static function cross( v:Num3, w:Num3, targetN:Num3 = null ):Num3
		{
			if(!targetN) targetN = ZERO; 
			 
			targetN.reset((w.y * v.z) - (w.z * v.y), (w.z * v.x) - (w.x * v.z), (w.x * v.y) - (w.y * v.x));
			return targetN; 
		}
		
		public function normalize():void
		{
			var mod:Number = this.modulo;

			if( mod != 0 && mod != 1)
			{
				this.x /= mod;
				this.y /= mod;
				this.z /= mod;
			}
		}
		
		public function multiplyEq(n:Number):void
		{
			x*=n; 
			y*=n;
			z*=n; 	
		}
		
		public function plusEq(v:Num3):void
		{
			x+=v.x; 
			y+=v.y; 
			z+=v.z; 	
		}
		
		public function minusEq(v:Num3):void
		{
			x -= v.x; 
			y -= v.y; 
			z -= v.z; 	
			
		}
		
		public function isModuloLessThan(v:Number):Boolean
		{
				
			return (moduloSquared<(v*v)); 
			
		}
		
		public function isModuloGreaterThan(v:Number):Boolean
		{
				
			return (moduloSquared>(v*v)); 
			
		}
		public function isModuloEqualTo(v:Number):Boolean
		{
				
			return (moduloSquared==(v*v)); 
			
		}
			
		public function get moduloSquared():Number
		{
			return ( this.x*this.x + this.y*this.y + this.z*this.z );
		}
		
		static public function get ZERO():Num3
		{
			return new Num3( 0, 0, 0 );
		}
		
		public function toString(): String
		{
			return '[' + Math.round(x * 100) / 100 + ',' + Math.round(y * 100) / 100 + ',' + Math.round(z * 100) / 100 + ']';		
		
		}
		
		public function rotateX(angle:Number) :void
		{
			var cosRY:Number = Math.cos(angle);
			var sinRY:Number = Math.sin(angle);

			temp.copyFrom(this); 

			this.y = temp.y * cosRY - temp.z * sinRY;
			this.z = temp.y * sinRY + temp.z * cosRY;
			
		}	

		public function rotateY(angle:Number) :void
		{
			var cosRY:Number = Math.cos(angle);
			var sinRY:Number = Math.sin(angle);

			temp.copyFrom(this); 
			
			this.x = temp.x * cosRY + temp.z * sinRY;
			this.z = -temp.x * sinRY + temp.z * cosRY;
			
			
		}	
		public function rotateZ(angle:Number) :void
		{
			var cosRY:Number = Math.cos(angle);
			var sinRY:Number = Math.sin(angle);

			temp.copyFrom(this);
			
			this.x = temp.x * cosRY - temp.y * sinRY;
			this.y = temp.x * sinRY + temp.y * cosRY;
			
			
		}
	}
}